#include "stdafx.h"
#include "../Engine/BuildingMaterialManager.hpp"

namespace he
{
	BuildingMaterialManager::BuildingMaterialManager(boost::filesystem::path const &Path)
	{
		boost::filesystem::path const full_path = Path/"data"/"building.xml";
		// If file doesn't exist
		if(!boost::filesystem::exists(full_path))
			throw std::runtime_error("Building file '" + full_path.string() + "' not found.");
		// Open file
		std::ifstream terrain_file(full_path.string().c_str());
		// Read the content of file
		std::ostringstream file_content;
		file_content << terrain_file.rdbuf();
		// Get the string
		std::string const content_string = file_content.str();
		boost::scoped_array<char> p_array(new char[content_string.size() + 1]);
		strcpy(p_array.get(), content_string.c_str());
		// Parse file
		typedef rapidxml::xml_node<> XmlNode_t;
		rapidxml::xml_document<> doc;
		doc.parse<0>(p_array.get());
		// Get the root node
		XmlNode_t *p_root = doc.first_node();
		// Get all building definitions
		for(XmlNode_t *p_node = p_root->first_node("item"); p_node != nullptr; p_node = p_node->next_sibling())
		{
			rapidxml::xml_attribute<> *p_attr = p_node->first_attribute("type");
			// Get the building type
			std::uint_least8_t const type = static_cast<std::uint_least8_t>(Convert::to_uint32(p_attr->value()));
			// Get material used
			std::get<0>(m_Buildings[type]) = p_node->first_attribute("material")->value();
			// Get all outside
			for(XmlNode_t *p_type_node = p_node->first_node("outside")->first_node(); p_type_node; p_type_node = p_type_node->next_sibling())
			{
				// At texture atlas info
				std::get<1>(m_Buildings[type]).push_back(
					TextureAtlasInfo_t(static_cast<float>(Convert::to_double(p_type_node->first_attribute("woffset")->value())),
					static_cast<float>(Convert::to_double(p_type_node->first_attribute("hoffset")->value())),
					static_cast<float>(Convert::to_double(p_type_node->first_attribute("width")->value())),
					static_cast<float>(Convert::to_double(p_type_node->first_attribute("height")->value()))
					)
				);
			}
			// Get all outside
			for(XmlNode_t *p_type_node = p_node->first_node("inside")->first_node(); p_type_node; p_type_node = p_type_node->next_sibling())
			{
				// At texture atlas info
				std::get<2>(m_Buildings[type]).push_back(
					TextureAtlasInfo_t(static_cast<float>(Convert::to_double(p_type_node->first_attribute("woffset")->value())),
					static_cast<float>(Convert::to_double(p_type_node->first_attribute("hoffset")->value())),
					static_cast<float>(Convert::to_double(p_type_node->first_attribute("width")->value())),
					static_cast<float>(Convert::to_double(p_type_node->first_attribute("height")->value()))
					)
				);
			}
		}
	}

	std::string BuildingMaterialManager::material_name(std::uint_least8_t Type) const
	{
		return std::get<0>(material_tuple(Type));
	}

	TextureAtlasInfo_t BuildingMaterialManager::variant_info_outside(std::uint_least8_t Type, std::uint_least8_t Variant) const
	{
		return std::get<1>(material_tuple(Type)).at(Variant);
	}

	TextureAtlasInfo_t BuildingMaterialManager::variant_info_inside(std::uint_least8_t Type, std::uint_least8_t Variant) const
	{
		return std::get<2>(material_tuple(Type)).at(Variant);
	}

	BuildingMaterialManager::BuildingTextureAtlasTuple_t const &BuildingMaterialManager::material_tuple(std::uint_least8_t Type) const
	{
		auto it = m_Buildings.find(Type);
		if(it == m_Buildings.end())
			throw std::runtime_error("BuildingMaterialManager: Cannot find material tuple");

		return it->second;
	}
} /*he*/
